<?php


namespace App\Services;

use App\DTOS\Admin\CustomerDTO;
use App\Exceptions\ServiceException;
use App\Models\ChannelCustomer;
use App\Models\Customer;
use App\Models\Game\BanList;
use App\Models\Game\Sale;
use App\Models\Game\LoginNum;
use App\Models\SimulationLogin;
use App\Services\Game\DouyinService;
use App\Services\Game\YiyouService;
use App\Utils\MyLog;
use App\Utils\ResponseUtil;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Nette\Utils\Random;

class ChennalCustomerService
{

    private IdentifyService $identifyService;
    private SmsService $smsService;
    private DouyinService $DouyinService;
    private YiyouService $yiyouService;

    /**
     * CustomerService constructor.
     * @param IdentifyService $identifyService
     * @param SmsService $smsService
     * @param DouyinService $DouyinService
     */
    public function __construct(IdentifyService $identifyService,SmsService $smsService,DouyinService $DouyinService,YiyouService $yiyouService)
    {
        $this->identifyService = $identifyService;
        $this->smsService = $smsService;
        $this->DouyinService = $DouyinService;
        $this->yiyouService = $yiyouService;
    }

    /**
     * @param CustomerDTO $customerDTO
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function paginate(CustomerDTO $customerDTO){

        $customerIds = $customerDTO->getCustomerIds();//角色列表
        $phones = $customerDTO->getPhones();//角色列表
        $phone = $customerDTO->getPhone();
        $realName = $customerDTO->getRealName();
        $page = $customerDTO->getPage();
        $pageSize = $customerDTO->getLimit();
        $invite_code = $customerDTO->getInviteCode();
        $channelType = $customerDTO->getChannelType();
        $customerId = $customerDTO->getCustomerId();
        $mobiles= $customerDTO->getMobiles();//手机列表
        $mobile = $customerDTO->getMobile();
        $model = ChannelCustomer::query();

        if ($customerId){
            $model->where('id',$customerId);
        }
        if ($channelType){
            $model->where('channel_type',$channelType);
        }
        if ($phone) {
            $model->where('phone','like','%'.$phone.'%');
        }
        if ($mobile) {
            $model->where('mobil','like','%'.$phone.'%');
        }
        if ($realName) {
            $model->where('real_name','like','%'.$realName.'%');
        }
        if ($invite_code){
            $model->where('invite_code',$invite_code);
        }
        if ($customerIds){
            $customerIdlists = explode("\n",$customerIds);
                $model->whereIn('id',$customerIdlists);
        }
        if ($phones){
            $phoneids = explode("\n",$phones);
            $model->whereIn('phone',$phoneids);
        }
        if ($mobiles){
            $mobileids = explode("\n",$mobiles);
            $model->whereIn('mobil',$mobileids);
        }
        return $model->orderByDesc('id')->paginate($pageSize,'*','page',$page);
    }

    public function register(CustomerDTO $customerDTO)
    {
        DB::beginTransaction();
        try {
            $insert = [];
            $phone = $customerDTO->getPhone();
            $password = $customerDTO->getPassword();
            if (!preg_match("/^[a-zA-Z0-9]+$/",$password)){
                throw new ServiceException('密码仅支持数字和字母');
            }
            $realName = $customerDTO->getRealName();
            $inviteCode = strtoupper($customerDTO->getInviteCode());
            $identityCode = strtoupper($customerDTO->getIdentityCode());
            $packageNo = $customerDTO->getPackageNo();
            if ($packageNo){
                $insert['package_no'] = $packageNo;
            }
            $insert['phone'] = $phone;
            $insert['password'] = Crypt::encryptString($password);
            $insert['real_name'] = $customerDTO->getRealName();
            $insert['identity_code'] = $identityCode;
            $insert['updated_at'] = $insert['created_at'] = now();

            $messageCode = $customerDTO->getMessageCode();
            if (!isPhone($phone)){
                throw new ServiceException('注册失败,手机号格式错误');
            }
            //验证验证码
            if ($messageCode != Redis::get('registerCode_'.$phone)){
                throw new ServiceException('验证码错误');
            }
            if (Customer::query()->where('identity_code',$identityCode)->count() >= 5){
                throw new ServiceException('此身份证已注册了5个账号');
            }
            if (Customer::query()->where('phone',$phone)->exists()){
                throw new ServiceException('此账号已经存在');
            }
            if (calculateAgeByIDCard($identityCode)<16){
                throw new ServiceException('身份证小于16岁');
            }
            if (!$this->identifyService->verify2($realName,$identityCode)){
                throw new ServiceException('实名认证失败');
            }
            Redis::set('registerCode_'.$phone,null);
            $insert['id'] = getSnowFlakeId();
            //处理邀请码
            if ($inviteCode){
                $inviteCodeModel = Sale::query()->where('code',$inviteCode)->first();
                if (!$inviteCodeModel || empty(data_get($inviteCodeModel,'code'))){
                    throw new ServiceException('邀请码无效');
                }
                $insert['invite_code'] = $inviteCode;
            }
            DB::commit();
            return Customer::query()->insert($insert);
        } catch (ServiceException $e){
            DB::rollBack();
            throw $e;
        } catch (\Exception $e){
            DB::rollBack();
            throw new ServiceException($e->getMessage());
        }
    }

    public function getRegisterCode($phone){
        if (!$phone){
            throw new ServiceException('请填写手机号');
        }
        if(!isPhone($phone)){
            throw new ServiceException('手机号格式不正确');
        }
        if (Customer::query()->where('phone',$phone)->exists()){
            throw new ServiceException('当前手机号已经注册');
        }
        try{
            $code = Random::generate(6,'0-9');//验证码
            $send = false;
            if (config('app.env') == '204'){ //SmsService $smsService;
                $send = $this->smsService->sendMessage($phone,$code,config('Sms.xmMobileRegister'));
            }
            Redis::setex('registerCode_'.$phone,300,$code); //保存到缓存中
            Log::info("$phone : $code , send : $send");
            return true;
        }catch(\Exception $e){
            return ResponseUtil::error($e->getMessage());
        }
    }

    /**
     * @param $phone
     * @param $password
     * @return \Illuminate\Database\Eloquent\HigherOrderBuilderProxy|mixed
     * @throws int|\Exception
     */
    public function companyLogin($phone,$password){ //官方登录
        DB::beginTransaction();
        if (!$phone || !$password){
            throw new \Exception('账号和密码不允许为空');
        }
        $customer = Customer::query()->where('phone',$phone)->first();
        if (!$customer){
            throw new \Exception('账号或密码错误');
        }
        if (Crypt::decryptString($customer->password) != $password){
            throw new \Exception('账号或密码错误');
        }

        DB::commit();
        //判断是否是模拟登录
        if ($simulationLogin = SimulationLogin::query()->where('target_id',$customer->id)->first()) {
            return (int)$simulationLogin->from_id;
        }
        return $customer->id;
    }

    /**
     * @param $accessToken
     * @return \Illuminate\Database\Eloquent\HigherOrderBuilderProxy|int|mixed
     * @throws int|\Exception
     */
    public function douyinLogin($accessToken){ //抖音登录
        $data = $this->DouyinService->login($accessToken);
        $sdk_open_id = data_get($data,'sdk_open_id'); //用户唯一标识
        // $age_type = data_get($data,'age_type'); // -1 未实名, 8 0-8岁 ; 16 8-16岁 18 16-18 100 100 18~
        $customer = Customer::query()->where('channel_uuid',$sdk_open_id)->first();
        $customerId = null;
        if ($customer) {
            $customerId = $customer->id;
        } else {
            $customerId = getSnowFlakeId();
            Customer::query()->insertGetId([ //新增用户数据
                'id'=>$customerId,
                'channel_uuid'=>$sdk_open_id,
                'channel_type'=>2,
                'created_at'=>date("Y-m-d H:i:s"),
            ]);
        }

        if (SimulationLogin::query()->where('from_id',$customerId)->exists()){ //被模拟登录了
            throw new ServiceException('官方技术正在查看你的账号,请稍后再试');
        }
        return $customerId;
    }

    public function yiyouLogin($accessToken) //易游登录
    {
        $arr = explode("_",$accessToken);
        $memId = $arr[0];
        $customer = Customer::query()->where('channel_uuid',$memId)->first();
        if ($customer) {
            $customerId = $customer->id;
        } else {
            $customerId = getSnowFlakeId();
            $data = $this->yiyouService->login($accessToken);
            $menId = data_get($data,'mem_id');
            if ($menId){
                Customer::query()->insertGetId([ //新增用户数据
                    'id'=>$customerId,
                    'channel_uuid'=>$memId,
                    'channel_type'=>3,
                    'created_at'=>date("Y-m-d H:i:s"),
                ]);
            } else {
                throw new ServiceException('登录失败');
            }
        }
        if (SimulationLogin::query()->where('from_id',$customerId)->exists()){ //被模拟登录了
            throw new ServiceException('官方技术正在查看你的账号,请稍后再试');
        }
        return $customerId;
    }

}
